﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.ComponentModel;
using System.IO;
using System.Net.Cache;
using System.Windows.Threading;

namespace VideoAsset
{
    /// <summary>
    /// Custom list view
    /// </summary>
    public class ImageView : ViewBase
    {
        #region DefaultStyleKey

        protected override object DefaultStyleKey
        {
            get { return new ComponentResourceKey(GetType(), "ImageView"); }
        }

        #endregion

        #region ItemContainerDefaultStyleKey

        protected override object ItemContainerDefaultStyleKey
        {
            get { return new ComponentResourceKey(GetType(), "ImageViewItem"); }
        }

        #endregion
    }

    
//         public static readonly RoutedEvent OnClickMeClickedEvent =
//             EventManager.RegisterRoutedEvent("OnScrollChanged", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(ImageView));
// 
//         static ExampleControl()
//         {
//             DefaultStyleKeyProperty.OverrideMetadata(typeof(ExampleControl), new FrameworkPropertyMetadata(typeof(ExampleControl)));
//         }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 
    public partial class MainWindow : Window
    {
        public List<VideoAssets.VideoFileInfo> m_videoList;
        public List<VideoAssets.VideoFileInfo> m_dbVideoList;        
        public List<string> m_actorList;
        public List<string> m_typeFilters;
        public VideoAssets m_videoAsset = null;
        private BitmapImage m_videoCover = null;
        //private CroppedBitmap m_videoCoverView = null;
        private string m_lastVideoCover = null;
        private GridViewColumnHeader m_lastHeaderClicked = null;
        private ListSortDirection m_lastDirection = ListSortDirection.Ascending;
        private string m_currentActorFilter = null;
        private string m_currentTitleFilter = null;
        private string m_currentTypeFilter = null;
        private UInt32 m_qualityLow = 0;
        private UInt32 m_qualityHigh = 65535;
        private const string COVER_DEFAULT = "images\\refresh.jpg";
        private ViewBase m_filesImageView;
        private ViewBase m_filesListView;

        private DispatcherTimer m_timer;

        public MainWindow()
        {
            InitializeComponent();        
        }

        private void InitTimer()
        {
            //  DispatcherTimer setup
            m_timer = new System.Windows.Threading.DispatcherTimer();
            m_timer.Tick += new EventHandler((s, e) =>
            {
                if (m_videoAsset.m_writeProgess > 0)
                {
                    WriteProgress.Visibility = Visibility.Visible;
                    WriteProgress.Value = m_videoAsset.m_writeProgess;
                }
                else
                {
                    WriteProgress.Visibility = Visibility.Hidden;
                }
            });
            m_timer.Interval = new TimeSpan(0, 0, 1);
            m_timer.Start();
        }

        private void ClearAllFilters()
        {            
            //view.Filter = null;            
            ComboboxActors.SelectedIndex = 0;
            ComboboxQuality.SelectedIndex = 0;
            ComboboxType.SelectedIndex = 0;
            TextBoxTitleFilter.Text = "";            
            InitQualityLevel();
            InitTypeFilter();

            CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(FilesListView.ItemsSource);
            view.Refresh();
        }

        private bool VideoFilters(object item)
        {
            VideoAssets.VideoFileInfo vfi = item as VideoAssets.VideoFileInfo;
            if (vfi != null)
            {
                return ActorFilter(vfi) && TitleFilter(vfi) && QualityFilter(vfi) && TypeFilter(vfi);
            }
            return false;
        }
        private bool ActorFilter(VideoAssets.VideoFileInfo vfi)
        {
            return (vfi.act == m_currentActorFilter) || (m_currentActorFilter == "All");
        }

        private bool TitleFilter(VideoAssets.VideoFileInfo vfi)
        {
            if (!String.IsNullOrEmpty(m_currentTitleFilter))
            {
                return (vfi.title.ToLower().IndexOf(m_currentTitleFilter.ToLower()) >= 0 ||
                        vfi.name.ToLower().IndexOf(m_currentTitleFilter.ToLower()) >= 0);
            }
            return true;
        }

        private bool QualityFilter(VideoAssets.VideoFileInfo vfi)
        {
            if (vfi.info.resY >= m_qualityLow && vfi.info.resY < m_qualityHigh)
            {
                return true;
            }
            return false;
        }

        #region type filter

        private void InitTypeFilterPath()
        {
            m_typeFilters = new List<string>();
            m_typeFilters.Add("\\us\\");
            m_typeFilters.Add("cartoon\\");
            m_typeFilters.Add("anim\\");
            InitTypeFilter();
        }

        private bool TypeFilter(VideoAssets.VideoFileInfo vfi)
        {
            if (m_currentTypeFilter == "W")
            {
                return (vfi.name.IndexOf(m_typeFilters[0]) != -1);
            }
            else if (m_currentTypeFilter == "C")
            {
                foreach (string filter in m_typeFilters.Skip(1))
                {
                    if (vfi.name.IndexOf(filter) != -1)
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (m_currentTypeFilter == "J")
            {
                foreach (string filter in m_typeFilters)
                {
                    if (vfi.name.IndexOf(filter) != -1)
                    {
                        return false;
                    }
                }
                return true;
            }
            return true;
        }
        
        private void InitTypeFilter()
        {
            m_currentTypeFilter = "J";
        }
        #endregion

        private void InitVideoAsset()
        {
            m_videoAsset.InitDB();
            m_videoAsset.UpdateFileList();
            m_videoList = m_videoAsset.m_fileList;
            m_dbVideoList = m_videoAsset.m_dbFileDict.Values.ToList();
            m_actorList = m_videoAsset.m_actorList;
            m_actorList.Insert(0, "All");

            //Initialize list view
            FilesListView.ItemsSource = m_videoList;

            ICollectionView view = CollectionViewSource.GetDefaultView(FilesListView.ItemsSource);
            view.Filter = VideoFilters;
            view.Refresh();

            ComboboxActors.ItemsSource = m_actorList;            
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            m_videoAsset = new VideoAssets();
            InitVideoAsset();
            InitTypeFilterPath();

            m_filesImageView = FilesListView.View;
            m_filesListView = FilesListView.FindResource("FilesListView") as ViewBase;

            FilesListView.View = m_filesListView;

            InitTimer();
            ClearAllFilters();
        }

        private void FilesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var item = (sender as ListView).SelectedItem;
            if (item != null)
            {                
                VideoAssets.VideoFileInfo vfi = item as VideoAssets.VideoFileInfo;
                // displace video info
                PropertyText.Text = "";
                PropertyText.Inlines.Add(new Bold(new Run("Title: ")));
                PropertyText.Inlines.Add(new Run(vfi.title));
                PropertyText.Inlines.Add(new Bold(new Run("    Actor: ")));
                PropertyText.Inlines.Add(new Run(vfi.act));
                PropertyText.Inlines.Add(new Run("\r\n"));
                PropertyText.Inlines.Add(new Bold(new Run("Path: ")));
                PropertyText.Inlines.Add(new Run(vfi.name));

                // display cover on property window                
                if (vfi.coverPath == COVER_DEFAULT)
                {
                    GetCoverPath(vfi);                    
                }
                
               string img = vfi.coverPath;
                if (m_lastVideoCover != img)
                {
                    m_videoCover = null;
                    //m_videoCoverView = null;
                    if ((new FileInfo(img)).Exists)
                    {
                        m_videoCover = new BitmapImage();
                        //load image
                        m_videoCover.BeginInit();
                        m_videoCover.CacheOption = BitmapCacheOption.None;
                        m_videoCover.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
                        m_videoCover.CacheOption = BitmapCacheOption.OnLoad;
                        m_videoCover.CreateOptions = BitmapCreateOptions.IgnoreImageCache | BitmapCreateOptions.IgnoreColorProfile;
                        m_videoCover.UriSource = new Uri(img);
                        m_videoCover.EndInit();

                        // crop image, only use the right half part
                        //m_videoCoverView = new CroppedBitmap(m_videoCover, new Int32Rect((int)m_videoCover.Width / 2, 0, (int)m_videoCover.Width / 2, (int)m_videoCover.Height));
                    }
                    m_lastVideoCover = img;
                }
               PropertyImage.Source = m_videoCover;
            }            
        }

        private void ListViewSort(string sortBy, ListSortDirection direction)
        {
            ICollectionView dataView = CollectionViewSource.GetDefaultView(FilesListView.ItemsSource);

            dataView.SortDescriptions.Clear();
            SortDescription sd = new SortDescription(sortBy, direction);
            dataView.SortDescriptions.Add(sd);
            dataView.Refresh();
        }

        private void FilesListView_olumnHeaderClick(object sender, RoutedEventArgs e)
        {
            GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader;
            ListSortDirection direction;

            if (headerClicked != null)
            {
                if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
                {
                    if (headerClicked != m_lastHeaderClicked)
                    {
                        direction = ListSortDirection.Ascending;
                    }
                    else
                    {
                        if (m_lastDirection == ListSortDirection.Ascending)
                        {
                            direction = ListSortDirection.Descending;
                        }
                        else
                        {
                            direction = ListSortDirection.Ascending;
                        }
                    }

                    string header = headerClicked.Column.Header as string;
                    ListViewSort(header, direction);

                    if (direction == ListSortDirection.Ascending)
                    {
                        headerClicked.Column.HeaderTemplate =
                          Resources["HeaderTemplateArrowUp"] as DataTemplate;
                    }
                    else
                    {
                        headerClicked.Column.HeaderTemplate =
                          Resources["HeaderTemplateArrowDown"] as DataTemplate;
                    }

                    // Remove arrow from previously sorted header 
                    if (m_lastHeaderClicked != null && m_lastHeaderClicked != headerClicked)
                    {
                        m_lastHeaderClicked.Column.HeaderTemplate = null;
                    }


                    m_lastHeaderClicked = headerClicked;
                    m_lastDirection = direction;
                }
            }
        }

        private void FilesListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var item = ((FrameworkElement)e.OriginalSource).DataContext as VideoAssets.VideoFileInfo;
            if (item != null)
            {
                OpenVideo(item.name);
            }
        }

        private void OpenVideo(string videoName)
        {
            if ((new FileInfo(videoName).Exists))
            {
                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.EnableRaisingEvents = false;
                proc.StartInfo.FileName = videoName;
                proc.Start();
            }
        }

        private void ListViewFilterChanged()
        {
            CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(FilesListView.ItemsSource);
            view.Filter = VideoFilters;
            view.Refresh();
            FilesListView.SelectedIndex = 0;
        }

        private void InitQualityLevel()
        {
            m_qualityLow = 0;
            m_qualityHigh = 65535;
        }

        private void QualityFilterChanged(string quality)
        {
            if (quality == "All")
            {
                InitQualityLevel();                
            }
            else if (quality == "DVD")
            {
                m_qualityLow = 0;
                m_qualityHigh = 720;
            }
            else if (quality == "HD")
            {
                m_qualityLow = 720;
                m_qualityHigh = 1000;
            }
            else if (quality == "FHD")
            {
                m_qualityLow = 1000;
                m_qualityHigh = 2160;
            }
            
            ListViewFilterChanged();
        }

        private void TypeFilterChanged(string type)
        {
            m_currentTypeFilter = type;
            ListViewFilterChanged();
        }

        private void ComboboxActors_DropDownClosed(object sender, EventArgs e)
        {
            var item = (sender as ComboBox).SelectedItem;
            if (item != null)
            {
                m_currentActorFilter = item as string;
                ListViewFilterChanged();
            }
        }

        private void ComboboxActors_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var item = (sender as ComboBox).SelectedItem;
            if (item != null)
            {
                m_currentActorFilter = item as string;
                ListViewFilterChanged();
            }
        }

        private void ComboBoxQuality_DropDownClosed(object sender, EventArgs e)
        {
            var item = (sender as ComboBox).SelectedItem;
            if (item != null)
            {
                string quality = (item as ComboBoxItem).Content as string;
                QualityFilterChanged(quality);
            }
        }

        private void ComboBoxQuality_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var item = (sender as ComboBox).SelectedItem;
            if(item != null)
            {
                string quality = (item as ComboBoxItem).Content as string;
                QualityFilterChanged(quality);
            }
        }

        private void ComboBoxType_DropDownClosed(object sender, EventArgs e)
        {
            var item = (sender as ComboBox).SelectedItem;
            if (item != null)
            {
                string type = (item as ComboBoxItem).Content as string;
                TypeFilterChanged(type);
            }
        }

        private void ComboBoxType_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var item = (sender as ComboBox).SelectedItem;
            if (item != null)
            {
                string type = (item as ComboBoxItem).Content as string;
                TypeFilterChanged(type);
            }
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            m_currentTitleFilter = (sender as TextBox).Text;
            ListViewFilterChanged();
        }

        private void Button_Local_Click(object sender, RoutedEventArgs e)
        {
            if (FilesListView.ItemsSource != m_videoList)
            {
                FilesListView.ItemsSource = m_videoList;
                ListViewFilterChanged();
            }     
        }

        private void Button_Click_Refresh(object sender, RoutedEventArgs e)
        {
            InitVideoAsset();
        }
        

        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Return)
            {
                m_currentTitleFilter = (sender as TextBox).Text;
                ListViewFilterChanged();
            }
        }

        private void FilesListView_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Return)
            {
                var item = ((FrameworkElement)e.OriginalSource).DataContext as VideoAssets.VideoFileInfo;
                if (item != null)
                {
                    OpenVideo(item.name);
                }               

            }
        }

        private void LV_MENU_CopyFullPath_Click(object sender, RoutedEventArgs e)
        {
            VideoAssets.VideoFileInfo vfi = FilesListView.SelectedItem as VideoAssets.VideoFileInfo;
            Clipboard.SetDataObject(vfi.name);
        }

        private void LV_MENU_OpenPath_Click(object sender, RoutedEventArgs e)
        {
            VideoAssets.VideoFileInfo vfi = FilesListView.SelectedItem as VideoAssets.VideoFileInfo;
            System.Diagnostics.Process.Start("explorer.exe","/select,\"" +  vfi.name + "\"");
        }

        private void LV_MENU_CopyTitle_Click(object sender, RoutedEventArgs e)
        {
            VideoAssets.VideoFileInfo vfi = FilesListView.SelectedItem as VideoAssets.VideoFileInfo;
            Clipboard.SetDataObject(wmvSegments.wmvCut.getFileNameNoExt(vfi.title));
        }

        private void LV_MENU_ActorFilter_Click(object sender, RoutedEventArgs e)
        {
            VideoAssets.VideoFileInfo vfi = FilesListView.SelectedItem as VideoAssets.VideoFileInfo;
            if (vfi.act != "")
            {
                m_currentActorFilter = vfi.act;
                ListViewFilterChanged();
            }
        }

        private void LV_MENU_Rename_Click(object sender, RoutedEventArgs e)
        {

        }        

        private void HandleScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            // virtualization, only load the visible items            
            if (FilesListView.View == m_filesImageView)
            {
                ShowVisibleItems(sender);
            }
        }

        private void GetCoverPath(VideoAssets.VideoFileInfo vfi)
        {
            if (vfi.exist)
            {
                string cp = Path.ChangeExtension(vfi.name, "jpg");
                if ((new FileInfo(cp)).Exists)
                {
                    vfi.coverPath = cp;
                }
            }
        }

        private void ShowVisibleItems(object sender)
        {
            var scrollViewer = (FrameworkElement)sender;
            int visibleItems = 0;
            foreach (var item in FilesListView.Items)
            {
                VideoAssets.VideoFileInfo vfi = item as VideoAssets.VideoFileInfo;
                var listBoxItem = (FrameworkElement)FilesListView.ItemContainerGenerator.ContainerFromItem(item);
                if (vfi.coverPath == COVER_DEFAULT && IsFullyOrPartiallyVisible(listBoxItem, scrollViewer) && visibleItems <= 50)
                {                    
                    GetCoverPath(vfi);
                    visibleItems++;
                }
            }
        }

        protected bool IsFullyOrPartiallyVisible(FrameworkElement child, FrameworkElement scrollViewer)
        {
            var childTransform = child.TransformToAncestor(scrollViewer);
            var childRectangle = childTransform.TransformBounds(
                                      new Rect(new Point(0, 0), child.RenderSize));
            var ownerRectangle = new Rect(new Point(0, 0), scrollViewer.RenderSize);
            return ownerRectangle.IntersectsWith(childRectangle);
        }

        private void Button_Click_ListView(object sender, RoutedEventArgs e)
        {
            FilesListView.View = m_filesListView;            
        }

        private void Button_Click_ImageView(object sender, RoutedEventArgs e)
        {
            FilesListView.View = m_filesImageView;            
        }

        private void Button_DB_Click(object sender, RoutedEventArgs e)
        {            
            if (FilesListView.ItemsSource != m_dbVideoList)
            {
                FilesListView.ItemsSource = m_dbVideoList;
                ListViewFilterChanged();
            }            
        }

        private void Button_Clear_Click(object sender, RoutedEventArgs e)
        {
            ClearAllFilters();
        }
    }
}
